#ifndef __MY_UTIL__
#define __MY_UTIL__
#include<iostream>
#include<fstream>
#include<string>
#include<memory>
#include<sstream>
#include<unistd.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<jsoncpp/json/json.h>

namespace aod
{
    //服务端工具类
    class FileUtil 
    {
    public:
        FileUtil(const std::string name):_name(name){}
        // 判断文件是否存在
        bool Exists()
        {
            int ret = access(_name.c_str(), F_OK); // F_OK专门用于检测文件是否存在：存在返回0，不存在返回-1
            if(ret != 0)
            {
                std::cout << "file is not exists!\n";
                return false;
            }
            return true;
        }

        // 获取文件大小
        size_t Size()
        {
            if(this->Exists() == false) return 0;
            struct stat st;
            int ret = stat(_name.c_str(), &st);
            if(ret != 0) 
            {
                std::cout << "get file stat failed!\n";   
                return 0;
            }
            return st.st_size;
        }

        // 读取文件数据到body中
        bool ReadContent(std::string *body)
        {
            std::ifstream ifs;
            ifs.open(_name, std::ios::binary); // 以二进制方式打开
            if(ifs.is_open() == false)
            {
                std::cout << "open failed!\n";
                return false;
            }
            size_t flen = this->Size();
            body->resize(flen);
            ifs.read(&(*body)[0], flen);
            //body[0] 是 std::string 对象的第一个字符，而不是字符串的底层缓冲区地址
            // (*body) 获取指针 body 指向的 std::string 对象，
            //然后 (*body)[0] 获取该字符串的第一个字符，&(*body)[0] 获取该字符的地址，也就是底层数据的起始位置
            if(ifs.good() == false)
            {
                std::cout << "read file content failed!\n";
                ifs.close();
                return false;
            }
            ifs.close();
            return true;
        }

        //向文件写入数据
        bool WriteContent(const std::string &body)
        {
            std::ofstream ofs;
            ofs.open(_name, std::ios::binary); // 以二进制方式打开
            if(ofs.is_open() == false)
            {
                std::cout << "open failed!\n";
                return false;
            }
            ofs.write(body.c_str(), body.size());
            if(ofs.good() == false)
            {
                std::cout << "write file content failed!\n";
                ofs.close();
                return false;
            }
            ofs.close();
            return true;
        }

        // 针对目录创建目录
        bool CreateDirectory()
        {
            if(this->Exists()) return true;
            mkdir(_name.c_str(),0777);
            return true;
        }
    private:
        std::string _name;
    };

    // Json工具类
    class JsonUtil
    {
    public:
        static bool Serialize(const Json::Value &value ,std::string *body)
        {
            Json::StreamWriterBuilder swb;
            std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());

            std::stringstream ss;
            int ret = sw->write(value, &ss);
            if(ret != 0)
            {
                std::cout << "Serialize failed!\n";
                return false;
            }
            *body = ss.str();
            return true;
        }

        static bool Unserialize(const std::string &body, Json::Value *value)
        {
            Json::CharReaderBuilder crb;
            std::unique_ptr<Json::CharReader> cr(crb.newCharReader());

            std::string err;
            bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), value, &err);
            if(ret == false)
            {
                std::cout << "Unserialize failed!\n";
                return false;
            }
            return true;
        }
    };
}

#endif